home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / unix / gnused.3 < prev    next >
Internet Message Format  |  1989-07-12  |  77KB

  1. Path: xanth!ames!apple!sun-barr!newstop!sun!swap!page
  2. From: page%swap@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i167:  gnused -gnu stream/script editor, Part03/03
  5. Message-ID: <115137@sun.Eng.Sun.COM>
  6. Date: 12 Jul 89 23:14:31 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 2375
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: ehoogerbeets@rose.waterloo.edu (Edwin Hoogerbeets)
  12. Posting-number: Volume 89, Issue 167
  13. Archive-name: unix/gnused.3
  14.  
  15. # This is a shell archive.
  16. # Remove anything above and including the cut line.
  17. # Then run the rest of the file through 'sh'.
  18. # Unpacked files will be owned by you and have default permissions.
  19. #----cut here-----cut here-----cut here-----cut here----#
  20. #!/bin/sh
  21. # shar: SHell ARchive
  22. # Run the following text through 'sh' to create:
  23. #    sed.1
  24. #    sed.c
  25. #    sed.man
  26. # This is archive 3 of a 3-part kit.
  27. # This archive created: Wed Jul 12 15:53:25 1989
  28. echo "extracting sed.1"
  29. sed 's/^X//' << \SHAR_EOF > sed.1
  30. X.TH SED 1 "1989 May 26" "GNU Project"
  31. X.UC 4
  32. X.SH NAME
  33. X.sp
  34. Xsed \- stream editor
  35. X.SH SYNOPSIS
  36. X.sp
  37. X.B sed
  38. X[
  39. X.B \-n
  40. X] [
  41. X.B \-e
  42. X.I script
  43. X] [
  44. X.B \-f
  45. X.I scriptfile
  46. X] [
  47. X.I files
  48. X]
  49. X...
  50. X.SH DESCRIPTION
  51. X.sp
  52. X.I Sed
  53. Xcopies the named files or the standard input to its standard output, while
  54. Xperforming certain operations specified in the command line
  55. X.IR script
  56. Xor in the file
  57. X.IR scriptfile.
  58. XIf no filenames are specified, the default input is the standard input.
  59. X.PP
  60. X.I Sed
  61. Xcyclically reads in input lines and places them in the pattern space.
  62. XThe pattern space is selected by some or all of the commands in the
  63. Xscript, and acted upon by these commands. The pattern space is then
  64. Xwritten to the output, and the next input is read. 
  65. X.PP
  66. XThe script (on the command line or in the script file) is composed of one or
  67. Xmore lines that have the following form:
  68. X.PP
  69. X[
  70. X.B range
  71. X] 
  72. X.B function
  73. X[ 
  74. X.B arguments
  75. X]
  76. X.PP
  77. XThe range refers to either a line address range or a regular expression in the
  78. Xstyle of 
  79. X.I ed(1).
  80. XThe range selects which input lines the function should act upon. 
  81. XIf the range is omitted, all input lines are selected.
  82. X.PP
  83. XThe line address is calculated sequentially from the first file to last,
  84. Xin order. A line address range may be either a single line number or two
  85. Xline numbers separated by a comma. A single number selects that line
  86. Xnumber to act upon, and two line numbers separated by a comma inclusively 
  87. Xselect all lines between those two numbers.
  88. X.PP
  89. XRegular expressions in sed differ from 
  90. X.I ed(1) 
  91. Xregular expressions in that the escape sequence `\en' matches a newline
  92. Xembedded in the pattern space.  A $ character may also be used to
  93. Xselect the last line of input.
  94. X.PP
  95. XThe following list of 
  96. X.I sed
  97. Xfunctions are preceded by a number indicating the maximum amount of line
  98. Xnumbers valid in the 
  99. X.B range 
  100. Xof the function. A (1) would indicate that the function can only take
  101. Xeffect after a certain line number and not a range of line numbers,
  102. Xwhile a (2) would indicate that either one line number or two are valid
  103. Xfor the function.
  104. X.PP
  105. XWhen a function takes a 
  106. X.I text
  107. Xargument, a newline in the 
  108. X.I text
  109. Xmay be escaped by placing a `\e' character before it, allowing multiline
  110. Xtexts. 
  111. X.PP
  112. XEmpty commands are ignored.
  113. X.PP
  114. XA 
  115. X.I wfile 
  116. Xor 
  117. X.I rfile 
  118. Xargument to a function must be at the end of a command
  119. Xline, and there must be exactly one space between the command and the
  120. Xfile name argument. There can be at most 10 wfile and rfile arguments.
  121. XAll 
  122. X.I wfile
  123. Xor 
  124. X.I rfile
  125. Xarguments are created before any input lines are read.
  126. X.TP
  127. X(1)\|a\e
  128. X.br
  129. X.ns
  130. X.TP
  131. X.I text
  132. X.br
  133. XAppend the
  134. X.I text
  135. Xto the output after the current pattern space.
  136. X.TP
  137. X.RI (2)\|b " label"
  138. XBranch to the 
  139. X.IR label 
  140. Xdefined with the `:' command. 
  141. XAn empty
  142. X.I label
  143. Ximplies a branch to the end of the script.
  144. X.TP
  145. X(2)\|c\e
  146. X.br
  147. X.ns
  148. X.TP
  149. X.I text
  150. X.br
  151. XChange text.
  152. XThe pattern space is unconditionally deleted and the 
  153. X.I text
  154. Xis written to the output following the range.
  155. X.TP
  156. X(2)\|d
  157. XDelete the pattern space.
  158. X.TP
  159. X(2)\|D
  160. XDelete the initial segment of the 
  161. Xpattern space up to and including the first newline.
  162. X(the pattern space may contain more than one line of text -- see the `N'
  163. Xcommand)
  164. X.TP
  165. X(2)\|g
  166. XOverwrite the pattern space with the 
  167. Xcontents of the hold space.
  168. X.TP
  169. X(2)\|G
  170. XAppend the contents of the hold space to the pattern space.
  171. X.TP
  172. X(2)\|h
  173. XHold the pattern space. The pattern space is copied into the hold space.
  174. X.TP
  175. X(2)\|H
  176. XAppend the pattern space to the hold space.
  177. X.TP
  178. X(1)\|i\e
  179. X.br
  180. X.ns
  181. X.TP
  182. X.I text
  183. X.br
  184. XInsert.
  185. XWrite
  186. X.I text
  187. Xto the output.
  188. X.TP
  189. X(2)\|n
  190. XFlush the pattern space to the output and read the next input line into
  191. Xthe pattern space.
  192. X.TP
  193. X(2)\|N
  194. XAppend the next line of input to the pattern space, inserting a newline
  195. Xcharacter between them.
  196. X.TP
  197. X(2)\|p
  198. XPrint.
  199. XWrite a copy of the pattern space to the output.
  200. X.TP
  201. X(2)\|P
  202. XWrite a copy of the pattern space up to and including the first
  203. Xnewline to the output.
  204. X.TP
  205. X(1)\|q
  206. XQuit and do not start a new cycle.
  207. X.TP
  208. X.RI (2)\|r " rfile"
  209. XRead the contents of
  210. X.IR rfile 
  211. Xand write them to the output.
  212. X.TP
  213. X.RI (2)\|s /regular\ expression/replacement/flags
  214. XSearch for the 
  215. X.I regular expression
  216. Xin the pattern space and replace it with the
  217. X.I replacement
  218. Xstring.
  219. XAny character may be used as a delimiter instead of the `/'.
  220. XThe flags argument may be any number of the following:
  221. X.RS
  222. X.TP
  223. Xg
  224. XGlobally substitute the 
  225. X.I replacement
  226. Xfor the 
  227. X.I regular expression.
  228. XNormally, only the first match is found, but g forces matching of all
  229. Xoccurances.
  230. X.TP
  231. Xp
  232. XPrint the pattern space if a replacement was made.
  233. X.TP
  234. X.RI w " wfile"
  235. XWrite
  236. Xthe pattern space to the end of 
  237. X.I wfile
  238. Xif a replacement was made. This must be the last flag argument if it is
  239. Xused.
  240. X.RE
  241. X.TP
  242. X.RI (2)\|t " label"
  243. XTest.
  244. XIf a substitution was made since the last time an input line was read
  245. Xinto the pattern space, or since the last `t' command, command branches 
  246. Xto the 
  247. X.I label.
  248. XAn empty
  249. X.I label
  250. Xmeans to branch to the end of the script.
  251. X.TP
  252. X.RI (2)\|w " wfile"
  253. XWrite the pattern space to the file
  254. X.IR wfile .
  255. X.TP
  256. X.RI (2)\|x
  257. XExchange the contents of the pattern and hold spaces.
  258. X.TP
  259. X.RI (2)\|y /string1/string2/
  260. XYank all characters in
  261. X.I string1
  262. Xand replace them with the corresponding characters in 
  263. X.I string2,
  264. Xwhich should be of equal length as
  265. X.I string1.
  266. X.TP
  267. X.RI (2)! " function"
  268. XApply the 
  269. X.I function
  270. Xto those lines not selected by the command.
  271. X.TP
  272. X.RI (0)\|: " label"
  273. XDeclare a 
  274. X.I label
  275. Xfor `b' and `t' commands to branch to.
  276. X.TP
  277. X(1)\|=
  278. XWrite the current line number to the output.
  279. X.TP
  280. X(2)\|{
  281. XPerform multiple commands on the range. The `{' character is followed by
  282. Xone or more commands to perform on the pattern space. A '}' character
  283. Xterminates the list of commands.
  284. X.SH OPTIONS
  285. X.TP 8
  286. X.B \-n
  287. Xsuppress the default output
  288. X.TP
  289. X.B \-e
  290. Xindicates that the next argument is a script. Useful for scripts
  291. Xstarting with a \- character.
  292. X.TP
  293. X.B \-f
  294. Xindicates that the following argument is a file containing a script
  295. Xof commands to
  296. X.B Sed.
  297. X.PP
  298. X.SH SEE ALSO
  299. Xed(1), grep(1), awk(1), lex(1)
  300. X.PP
  301. X.SH AVAILABILITY
  302. X.PP
  303. XGNU
  304. X.I sed
  305. Xis free; anyone may redistribute copies of
  306. X.I sed
  307. Xto
  308. Xanyone under the terms stated in the
  309. XGNU General Public License,
  310. Xa copy of which may be found in each copy of
  311. X.IR "GNU Emacs" .
  312. XSee also the comment at the beginning of the source code file sed.c.
  313. X.PP
  314. XCopies of GNU
  315. X.I sed
  316. Xmay sometimes be received packaged with distributions of Unix systems,
  317. Xbut it is never included in the scope of any license covering those
  318. Xsystems.  Such inclusion violates the terms on which distribution
  319. Xis permitted.  In fact, the primary purpose of the General Public
  320. XLicense is to prohibit anyone from attaching any other restrictions
  321. Xto redistribution of any of the Free Software Foundation programs.
  322. X
  323. SHAR_EOF
  324. echo "extracting sed.c"
  325. sed 's/^X//' << \SHAR_EOF > sed.c
  326. X/* sed.c        emulate the UN*X sed command.
  327. X   Copyright (C) 1989 Free Software Foundation, Inc.
  328. X
  329. X                       NO WARRANTY
  330. X
  331. X  BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
  332. XNO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
  333. XWHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
  334. XRICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
  335. XWITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
  336. XBUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  337. XFITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
  338. XAND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
  339. XDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
  340. XCORRECTION.
  341. X
  342. X IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  343. XSTALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
  344. XWHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
  345. XLIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
  346. XOTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  347. XUSE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
  348. XDATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
  349. XA FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
  350. XPROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
  351. XDAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  352. X
  353. X                GENERAL PUBLIC LICENSE TO COPY
  354. X
  355. X  1. You may copy and distribute verbatim copies of this source file
  356. Xas you receive it, in any medium, provided that you conspicuously
  357. Xand appropriately publish on each copy a valid copyright notice
  358. X"Copyright (C) 1989 Free Software Foundation, Inc.", and include
  359. Xfollowing the copyright notice a verbatim copy of the above disclaimer
  360. Xof warranty and of this License.
  361. X
  362. X  2. You may modify your copy or copies of this source file or
  363. Xany portion of it, and copy and distribute such modifications under
  364. Xthe terms of Paragraph 1 above, provided that you also do the following:
  365. X
  366. X    a) cause the modified files to carry prominent notices stating
  367. X    that you changed the files and the date of any change; and
  368. X
  369. X    b) cause the whole of any work that you distribute or publish,
  370. X    that in whole or in part contains or is a derivative of this
  371. X    program or any part thereof, to be licensed at no charge to all
  372. X    third parties on terms identical to those contained in this
  373. X    License Agreement (except that you may choose to grant more
  374. X    extensive warranty protection to third parties, at your option).
  375. X
  376. X    c) You may charge a distribution fee for the physical act of
  377. X    transferring a copy, and you may at your option offer warranty
  378. X    protection in exchange for a fee.
  379. X
  380. X  3. You may copy and distribute this program or any portion of it in
  381. Xcompiled, executable or object code form under the terms of Paragraphs
  382. X1 and 2 above provided that you do the following:
  383. X
  384. X    a) cause each such copy to be accompanied by the
  385. X    corresponding machine-readable source code, which must
  386. X    be distributed under the terms of Paragraphs 1 and 2 above; or,
  387. X
  388. X    b) cause each such copy to be accompanied by a
  389. X    written offer, with no time limit, to give any third party
  390. X    free (except for a nominal shipping charge) a machine readable
  391. X    copy of the corresponding source code, to be distributed
  392. X    under the terms of Paragraphs 1 and 2 above; or,
  393. X
  394. X    c) in the case of a recipient of this program in compiled, executable
  395. X    or object code form (without the corresponding source code) you
  396. X    shall cause copies you distribute to be accompanied by a copy
  397. X    of the written offer of source code which you received along
  398. X    with the copy you received.
  399. X
  400. X  4. You may not copy, sublicense, distribute or transfer this program
  401. Xexcept as expressly provided under this License Agreement.  Any attempt
  402. Xotherwise to copy, sublicense, distribute or transfer this program is void and
  403. Xyour rights to use the program under this License agreement shall be
  404. Xautomatically terminated.  However, parties who have received computer
  405. Xsoftware programs from you with this License Agreement will not have
  406. Xtheir licenses terminated so long as such parties remain in full compliance.
  407. X
  408. X  5. If you wish to incorporate parts of this program into other free
  409. Xprograms whose distribution conditions are different, write to the Free
  410. XSoftware Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
  411. Xworked out a simple rule that can be stated here, but we will often permit
  412. Xthis.  We will be guided by the two goals of preserving the free status of
  413. Xall derivatives of our free software and of promoting the sharing and reuse of
  414. Xsoftware.
  415. X
  416. X In other words, you are welcome to use, share and improve this program.
  417. X You are forbidden to forbid anyone else to use, share and improve
  418. X what you give them.   Help stamp out software-hoarding!  */
  419. X
  420. X#include <stdio.h>
  421. X#include <ctype.h>
  422. X#include "regex.h"
  423. X
  424. X#ifdef AZTEC_C
  425. X#define memcpy(dst,src,n) movmem((src),(dst),(n))
  426. X#define memset(src,value,howmany) setmem((src),(howmany),(value))
  427. X#define bcopy(s, d, n) movmem((s),(d),(n))
  428. X#endif
  429. X
  430. X/* Compile with 'gcc [-g] [-DHAS_UTILS] [-O] -o sed sed.c [-lutils]' */
  431. X/* Use '-DHAS_UTILS', -lutils if you if you have hack's utils library */
  432. X/* Add '-I. regex.c' if regex is not in the system include dir/library */
  433. X#ifdef USG
  434. X#define bcopy(s, d, n) ((void)memcpy((d),(s), (n)))
  435. X#endif
  436. X
  437. X/* Struct vector is used to describe a chunk of a sed program.  There is one
  438. X   vector for the main program, and one for each { } pair.
  439. X */
  440. Xstruct vector {
  441. X        struct sed_cmd *v;
  442. X        int v_length;
  443. X        int v_allocated;
  444. X        struct vector *up_one;
  445. X        struct vector *next_one;
  446. X};
  447. X
  448. X
  449. X/* Goto structure is used to hold both GOTO's and labels.  There are two
  450. X   separate lists, one of goto's, called 'jumps', and one of labels, called
  451. X   'labels'.
  452. X   the V element points to the descriptor for the program-chunk in which the
  453. X   goto was encountered.
  454. X   the v_index element counts which element of the vector actually IS the
  455. X   goto/label.  The first element of the vector is zero.
  456. X   the NAME element is the null-terminated name of the label.
  457. X   next is the next goto/label in the list
  458. X*/
  459. X
  460. Xstruct sed_label {
  461. X        struct vector *v;
  462. X        int v_index;
  463. X        char *name;
  464. X        struct sed_label *next;
  465. X};
  466. X
  467. X/* ADDR_TYPE is zero for a null address,
  468. X   one if addr_number is valid, or
  469. X   two if addr_regex is valid,
  470. X   three, if the address is '$'
  471. X
  472. X   Other values are undefined.
  473. X */
  474. X
  475. X#define ADDR_NULL       0
  476. X#define ADDR_NUM        1
  477. X#define ADDR_REGEX      2
  478. X#define ADDR_LAST       3
  479. X
  480. Xstruct addr {
  481. X        int     addr_type;
  482. X        struct re_pattern_buffer *addr_regex;
  483. X        int     addr_number;
  484. X};
  485. X
  486. X
  487. X/* Aflags:  If the low order bit is set, a1 has been
  488. X   matched; apply this command until a2 matches.
  489. X   If the next bit is set, apply this command to all
  490. X   lines that DON'T match the address(es).
  491. X */
  492. X
  493. X#define A1_MATCHED_BIT  01
  494. X#define ADDR_BANG_BIT   02
  495. X
  496. X
  497. Xstruct sed_cmd {
  498. X        struct addr a1,a2;
  499. X        int aflags;
  500. X
  501. X        char cmd;
  502. X
  503. X        union {
  504. X                /* This structure is used for a, i, and c commands */
  505. X                struct {
  506. X                        char *text;
  507. X                        int text_len;
  508. X                } cmd_txt;
  509. X
  510. X                /* This is used for b and t commands */
  511. X                struct sed_cmd *label;
  512. X
  513. X                /* This for r and w commands */
  514. X                FILE *io_file;
  515. X
  516. X                /* This for the hairy s command */
  517. X                /* For the flags var:
  518. X                   low order bit means the 'g' option was given,
  519. X                   next bit means the 'p' option was given,
  520. X                   and the next bit means a 'w' option was given,
  521. X                      and wio_file contains the file to write to. */
  522. X
  523. X#define S_GLOBAL_BIT    01
  524. X#define S_PRINT_BIT     02
  525. X#define S_WRITE_BIT     04
  526. X#define S_NUM_BIT       010
  527. X
  528. X                struct {
  529. X                        struct re_pattern_buffer *regx;
  530. X                        char *replacement;
  531. X                        int replace_length;
  532. X                        int flags;
  533. X                        int numb;
  534. X                        FILE *wio_file;
  535. X                } cmd_regex;
  536. X
  537. X                /* This for the y command */
  538. X                char *translate;
  539. X
  540. X                /* For { and } */
  541. X                struct vector *sub;
  542. X                struct sed_label *jump;
  543. X        } x;
  544. X};
  545. X
  546. X/* Sed operates a line at a time. */
  547. Xstruct line {
  548. X        char *text;             /* Pointer to line allocated by malloc. */
  549. X        int length;             /* Length of text. */
  550. X        int alloc;              /* Allocated space for text. */
  551. X};
  552. X
  553. X/* This for all you losing compilers out there that can't handle void * */
  554. X#ifdef __GNU__
  555. X#define VOID void
  556. X#else
  557. X#define VOID char
  558. X#endif
  559. X
  560. Xextern int optind;
  561. Xextern char *optarg;
  562. Xextern int getopt();
  563. X
  564. Xextern char *memchr();
  565. Xextern VOID *memmove();
  566. X
  567. Xextern VOID *ck_malloc(),*ck_realloc();
  568. Xextern VOID *init_buffer();
  569. Xextern char *get_buffer();
  570. Xextern FILE *ck_fopen();
  571. Xextern void ck_fclose();
  572. Xextern void ck_fwrite();
  573. Xextern void flush_buffer();
  574. Xextern void add1_buffer();
  575. X
  576. Xextern char *strdup();
  577. X
  578. Xstruct vector *compile_program();
  579. Xvoid savchar();
  580. Xstruct sed_label *setup_jump();
  581. Xvoid line_copy();
  582. Xvoid line_append();
  583. Xvoid append_pattern_space();
  584. X
  585. X#ifndef HAS_UTILS
  586. Xchar *myname;
  587. X#else
  588. Xextern char *myname;
  589. X#endif
  590. X/* This is a good idea */
  591. Xchar *version_string = "GNU sed version 1.02 (or so)";
  592. X/*      1.00    Began distributing this file
  593. X *      1.01    Added s/re/rep/[digits]
  594. X *              added #n as first line of script
  595. X *              added filename globbing
  596. X *              added 'l' command
  597. X *              All in the name of POSIX
  598. X *      1.02    Fixed D command
  599. X *              Added Amiga porting ifdefs
  600. X *              Edwin Hoogerbeets 1989
  601. X */
  602. X
  603. X/* If set, don't write out the line unless explictly told to */
  604. Xint no_default_output = 0;
  605. X
  606. X/* Current input line # */
  607. Xint input_line_number = 0;
  608. X
  609. X/* Are we on the last input file? */
  610. Xint last_input_file = 0;
  611. X
  612. X/* Have we hit EOF on the last input file? */
  613. Xint input_EOF = 0;
  614. X
  615. X/* non-zero if a quit command has been hit */
  616. Xint quit_cmd = 0;
  617. X
  618. X/* Have we done any replacements lately? */
  619. Xint replaced = 0;
  620. X
  621. X/* How many '{'s are we executing at the moment */
  622. Xint program_depth = 0;
  623. X
  624. X/* The current SED program */
  625. Xstruct vector *the_program = 0;
  626. X
  627. X/* */
  628. Xstruct sed_label *jumps = 0;
  629. Xstruct sed_label *labels = 0;
  630. X
  631. X/* The 'current' input line. */
  632. Xstruct line line;
  633. X
  634. X/* An input line that's been stored by later use by the program */
  635. Xstruct line hold;
  636. X
  637. X/* A 'line' to append to the current line when it comes time to write it out */
  638. Xstruct line append;
  639. X
  640. Xstatic char ONE_ADDR[] = "Command only uses one address";
  641. Xstatic char NO_ADDR[] = "Command doesn't take any addresses";
  642. Xstatic char LINE_JUNK[] ="Extra characters after command";
  643. Xstatic char BAD_EOF[] =  "Unexpected End-of-file";
  644. Xstatic char USAGE[] =   "Usage: %s [-n] [-e script...] [-f sfile...] [file...]\n";
  645. Xstatic char NO_REGEX[] = "No previous regular expression";
  646. X
  647. Xstruct re_pattern_buffer *last_regex;
  648. X
  649. XFILE *input_file;
  650. X
  651. Xint bad_input = 0;
  652. X
  653. Xmain(argc,argv)
  654. Xchar **argv;
  655. X{
  656. X        int opt;
  657. X        int compiled = 0;
  658. X        struct sed_label *go,*lbl;
  659. X
  660. X#ifdef AZTEC_C
  661. X        extern long _Heapsize;
  662. X
  663. X        _Heapsize = 80 * 1024;
  664. X#endif
  665. X
  666. X        myname=argv[0];
  667. X        while((opt=getopt(argc,argv,"ne:f:"))!=EOF) {
  668. X                switch(opt) {
  669. X                case 'n':
  670. X                        if(no_default_output)
  671. X                                panic(USAGE);
  672. X                        no_default_output++;
  673. X                        break;
  674. X                case 'e':
  675. X                        compile_string(optarg);
  676. X                        compiled++;
  677. X                        break;
  678. X                case 'f':
  679. X                        compile_file(optarg);
  680. X                        compiled++;
  681. X                        break;
  682. X                }
  683. X        }
  684. X        if(!compiled) {
  685. X                if(argc<=optind)
  686. X                        panic("No program to run\n");
  687. X                compile_string(argv[optind]);
  688. X                optind++;
  689. X        }
  690. X
  691. X        for(go=jumps;go;go=go->next) {
  692. X                for(lbl=labels;lbl;lbl=lbl->next)
  693. X                        if(!strcmp(lbl->name,go->name))
  694. X                                break;
  695. X                if(!lbl)
  696. X                        panic("Can't find label for jump to '%s'\n",go->name);
  697. X                go->v->v[go->v_index].x.jump=lbl;
  698. X        }
  699. X
  700. X        line.length=0;
  701. X        line.alloc=50;
  702. X        line.text=ck_malloc(50);
  703. X
  704. X        append.length=0;
  705. X        append.alloc=50;
  706. X        append.text=ck_malloc(50);
  707. X
  708. X        hold.length=0;
  709. X        hold.alloc=50;
  710. X        hold.text=ck_malloc(50);
  711. X
  712. X        if(argc<=optind) {
  713. X                last_input_file++;
  714. X                read_file("-");
  715. X        } else while(optind<argc) {
  716. X                if(optind==argc-1)
  717. X                        last_input_file++;
  718. X                read_file(argv[optind]);
  719. X                optind++;
  720. X                if(quit_cmd)
  721. X                        break;
  722. X        }
  723. X        if(bad_input)
  724. X                exit(2);
  725. X        exit(0);
  726. X}
  727. X
  728. Xchar *prog_start;
  729. Xchar *prog_end;
  730. Xchar *prog_cur;
  731. X
  732. Xchar *prog_name;
  733. XFILE *prog_file;
  734. X
  735. Xint prog_line = 1;
  736. X
  737. Xcompile_string(str)
  738. Xchar *str;
  739. X{
  740. X        prog_file = 0;
  741. X        prog_line=0;
  742. X        prog_start=prog_cur=str;
  743. X        prog_end=str+strlen(str);
  744. X        the_program=compile_program(the_program);
  745. X}
  746. X
  747. Xcompile_file(str)
  748. Xchar *str;
  749. X{
  750. X        FILE *file;
  751. X        int ch;
  752. X
  753. X        prog_start=prog_cur=prog_end=0;
  754. X        prog_name=str;
  755. X        prog_line=1;
  756. X        if(str[0]=='-' && str[1]=='\0')
  757. X                prog_file=stdin;
  758. X        else
  759. X                prog_file=ck_fopen(str,"r");
  760. X        ch=getc(prog_file);
  761. X        if(ch=='#') {
  762. X                ch=getc(prog_file);
  763. X                if(ch=='n')
  764. X                        no_default_output++;
  765. X                while(ch!=EOF && ch!='\n')
  766. X                        ch=getc(prog_file);
  767. X        } else if(ch!=EOF)
  768. X                ungetc(ch,prog_file);
  769. X        the_program=compile_program(the_program);
  770. X}
  771. X
  772. X#define MORE_CMDS 40
  773. X
  774. Xstruct vector *
  775. Xcompile_program(vector)
  776. Xstruct vector *vector;
  777. X{
  778. X        struct sed_cmd *cur_cmd;
  779. X        int     ch;
  780. X        int     slash;
  781. X        VOID    *b;
  782. X        char    *string;
  783. X        int     num;
  784. X
  785. X        FILE *compile_filename();
  786. X
  787. X        if(!vector) {
  788. X                vector=(struct vector *)ck_malloc(sizeof(struct vector));
  789. X                vector->v=(struct sed_cmd *)ck_malloc(MORE_CMDS*sizeof(struct sed_cmd));
  790. X                vector->v_allocated=MORE_CMDS;
  791. X                vector->v_length=0;
  792. X                vector->up_one = 0;
  793. X                vector->next_one = 0;
  794. X        }
  795. X        for(;;) {
  796. X                do ch=inchar();
  797. X                while(ch!=EOF && (isspace(ch) || ch=='\n' || ch==';'));
  798. X                if(ch==EOF)
  799. X                        break;
  800. X                savchar(ch);
  801. X
  802. X                if(vector->v_length==vector->v_allocated) {
  803. X                        vector->v=(struct sed_cmd *)ck_realloc((VOID *)vector->v,(vector->v_length+MORE_CMDS)*sizeof(struct sed_cmd));
  804. X                        vector->v_allocated+=MORE_CMDS;
  805. X                }
  806. X                cur_cmd=vector->v+vector->v_length;
  807. X                vector->v_length++;
  808. X
  809. X                cur_cmd->a1.addr_type=0;
  810. X                cur_cmd->a2.addr_type=0;
  811. X                cur_cmd->aflags=0;
  812. X                cur_cmd->cmd=0;
  813. X
  814. X        skip_comment:
  815. X                if(compile_address(&(cur_cmd->a1))) {
  816. X                        ch=inchar();
  817. X                        if(ch==',') {
  818. X                                do ch=inchar();
  819. X                                while(ch!=EOF && isspace(ch));
  820. X                                savchar(ch);
  821. X                                if(compile_address(&(cur_cmd->a2)))
  822. X                                        ;
  823. X                                else
  824. X                                        bad_prog("Unexpected ','");
  825. X                        } else
  826. X                                savchar(ch);
  827. X                }
  828. X                ch=inchar();
  829. X                if(ch==EOF)
  830. X                        break;
  831. X new_cmd:
  832. X                switch(ch) {
  833. X                case '#':
  834. X                        if(cur_cmd->a1.addr_type!=0)
  835. X                                bad_prog(NO_ADDR);
  836. X                        do ch=inchar();
  837. X                        while(ch!=EOF && ch!='\n');
  838. X                        goto skip_comment;
  839. X                case '!':
  840. X                        if(cur_cmd->aflags & ADDR_BANG_BIT)
  841. X                                bad_prog("Multiple '!'s");
  842. X                        cur_cmd->aflags|= ADDR_BANG_BIT;
  843. X                        do ch=inchar();
  844. X                        while(ch!=EOF && isspace(ch));
  845. X                        if(ch==EOF)
  846. X                                bad_prog(BAD_EOF);
  847. X                        /* savchar(ch); */
  848. X                        goto new_cmd;
  849. X                case 'a':
  850. X                case 'i':
  851. X                        if(cur_cmd->a2.addr_type!=0)
  852. X                                bad_prog(ONE_ADDR);
  853. X                        /* Fall Through */
  854. X                case 'c':
  855. X                        cur_cmd->cmd=ch;
  856. X                        if(inchar()!='\\' || inchar()!='\n')
  857. X                                bad_prog(LINE_JUNK);
  858. X                        b=init_buffer();
  859. X                        while((ch=inchar())!=EOF && ch!='\n') {
  860. X                                if(ch=='\\')
  861. X                                        ch=inchar();
  862. X                                add1_buffer(b,ch);
  863. X                        }
  864. X                        if(ch!=EOF)
  865. X                                add1_buffer(b,ch);
  866. X                        num=size_buffer(b);
  867. X                        string=(char *)ck_malloc(num);
  868. X                        bcopy(get_buffer(b),string,num);
  869. X                        flush_buffer(b);
  870. X                        cur_cmd->x.cmd_txt.text_len=num;
  871. X                        cur_cmd->x.cmd_txt.text=string;
  872. X                        break;
  873. X                case '{':
  874. X                        cur_cmd->cmd=ch;
  875. X                        program_depth++;
  876. X                        /* while((ch=inchar())!=EOF && ch!='\n')
  877. X                                if(!isspace(ch))
  878. X                                        bad_prog(LINE_JUNK); */
  879. X                        cur_cmd->x.sub=compile_program((struct vector *)0);
  880. X                        /* FOO JF is this the right thing to do? */
  881. X                        break;
  882. X                case '}':
  883. X                        if(!program_depth)
  884. X                                bad_prog("Unexpected '}'");
  885. X                        --(vector->v_length);
  886. X                        while((ch=inchar())!=EOF && ch!='\n')
  887. X                                if(!isspace(ch))
  888. X                                        bad_prog(LINE_JUNK);
  889. X                        return vector;
  890. X                case ':':
  891. X                        cur_cmd->cmd=ch;
  892. X                        if(cur_cmd->a1.addr_type!=0)
  893. X                                bad_prog(": doesn't want any addresses");
  894. X                        labels=setup_jump(labels,cur_cmd,vector);
  895. X                        break;
  896. X                case 'b':
  897. X                case 't':
  898. X                        cur_cmd->cmd=ch;
  899. X                        jumps=setup_jump(jumps,cur_cmd,vector);
  900. X                        break;
  901. X                case 'q':
  902. X                case '=':
  903. X                        if(cur_cmd->a2.addr_type)
  904. X                                bad_prog(ONE_ADDR);
  905. X                        /* Fall Through */
  906. X                case 'd':
  907. X                case 'D':
  908. X                case 'g':
  909. X                case 'G':
  910. X                case 'h':
  911. X                case 'H':
  912. X                case 'l':
  913. X                case 'n':
  914. X                case 'N':
  915. X                case 'p':
  916. X                case 'P':
  917. X                case 'x':
  918. X                        cur_cmd->cmd=ch;
  919. X                        do      ch=inchar();
  920. X                        while(ch!=EOF && isspace(ch) && ch!='\n' && ch!=';');
  921. X                        if(ch!='\n' && ch!=';' && ch!=EOF)
  922. X                                bad_prog(LINE_JUNK);
  923. X                        break;
  924. X
  925. X                case 'r':
  926. X                        if(cur_cmd->a2.addr_type!=0)
  927. X                                bad_prog(ONE_ADDR);
  928. X                        /* FALL THROUGH */
  929. X                case 'w':
  930. X                        cur_cmd->cmd=ch;
  931. X                        cur_cmd->x.io_file=compile_filename(ch=='r');
  932. X                        break;
  933. X
  934. X                case 's':
  935. X                        cur_cmd->cmd=ch;
  936. X                        b=init_buffer();
  937. X                        slash=inchar();
  938. X                        while((ch=inchar())!=EOF && ch!=slash) {
  939. X                                if(ch!='\\') {
  940. X                                        add1_buffer(b,ch);
  941. X                                        continue;
  942. X                                }
  943. X                                ch=inchar();
  944. X                                switch(ch) {
  945. X                                case 'n':
  946. X                                        add1_buffer(b,'\n');
  947. X                                        break;
  948. X                                /* case 'b':
  949. X                                        add1_buffer(b,'\b');
  950. X                                        break;
  951. X                                case 'f':
  952. X                                        add1_buffer(b,'\f');
  953. X                                        break;
  954. X                                case 'r':
  955. X                                        add1_buffer(b,'\r');
  956. X                                        break;
  957. X                                case 't':
  958. X                                        add1_buffer(b,'\t');
  959. X                                        break; */
  960. X                                case EOF:
  961. X                                        break;
  962. X                                default:
  963. X                                        add1_buffer(b,'\\');
  964. X                                        add1_buffer(b,ch);
  965. X                                        break;
  966. X                                }
  967. X                        }
  968. X                        if(ch==EOF)
  969. X                                bad_prog(BAD_EOF);
  970. X                        if(size_buffer(b)) {
  971. X                                last_regex=(struct re_pattern_buffer *)ck_malloc(sizeof(struct re_pattern_buffer));
  972. X                                last_regex->allocated=size_buffer(b);
  973. X                                last_regex->buffer=ck_malloc(last_regex->allocated);
  974. X                                last_regex->fastmap=0;
  975. X                                last_regex->translate=0;
  976. X                                re_compile_pattern(get_buffer(b),size_buffer(b),last_regex);
  977. X                        } else if(!last_regex)
  978. X                                bad_prog(NO_REGEX);
  979. X                        cur_cmd->x.cmd_regex.regx=last_regex;
  980. X                        flush_buffer(b);
  981. X
  982. X                        b=init_buffer();
  983. X                        while((ch=inchar())!=EOF && ch!=slash) {
  984. X                                if(ch=='\\') {
  985. X                                        int ci;
  986. X
  987. X                                        ci=inchar();
  988. X                                        if(ci!=EOF) {
  989. X                                                if(ci!='\n')
  990. X                                                        add1_buffer(b,ch);
  991. X                                                add1_buffer(b,ci);
  992. X                                        }
  993. X                                } else
  994. X                                        add1_buffer(b,ch);
  995. X                        }
  996. X                        cur_cmd->x.cmd_regex.replace_length=size_buffer(b);
  997. X                        cur_cmd->x.cmd_regex.replacement=ck_malloc(cur_cmd->x.cmd_regex.replace_length);
  998. X                        bcopy(get_buffer(b),cur_cmd->x.cmd_regex.replacement,cur_cmd->x.cmd_regex.replace_length);
  999. X                        flush_buffer(b);
  1000. X
  1001. X                        cur_cmd->x.cmd_regex.flags=0;
  1002. X                        cur_cmd->x.cmd_regex.numb=0;
  1003. X
  1004. X                        if(ch==EOF)
  1005. X                                break;
  1006. X                        do {
  1007. X                                ch=inchar();
  1008. X                                switch(ch) {
  1009. X                                case 'p':
  1010. X                                        if(cur_cmd->x.cmd_regex.flags&S_PRINT_BIT)
  1011. X                                                bad_prog("multiple 'p' options to 's' command");
  1012. X                                        cur_cmd->x.cmd_regex.flags|=S_PRINT_BIT;
  1013. X                                        break;
  1014. X                                case 'g':
  1015. X                                        if(cur_cmd->x.cmd_regex.flags&S_NUM_BIT)
  1016. X                                                cur_cmd->x.cmd_regex.flags&= ~S_NUM_BIT;
  1017. X                                        if(cur_cmd->x.cmd_regex.flags&S_GLOBAL_BIT)
  1018. X                                                bad_prog("multiple 'g' options to 's' command");
  1019. X                                        cur_cmd->x.cmd_regex.flags|=S_GLOBAL_BIT;
  1020. X                                        break;
  1021. X                                case 'w':
  1022. X                                        cur_cmd->x.cmd_regex.flags|=S_WRITE_BIT;
  1023. X                                        cur_cmd->x.cmd_regex.wio_file=compile_filename(0);
  1024. X                                        ch='\n';
  1025. X                                        break;
  1026. X                                case '0': case '1': case '2': case '3':
  1027. X                                case '4': case '5': case '6': case '7':
  1028. X                                case '8': case '9':
  1029. X                                        if(cur_cmd->x.cmd_regex.flags&S_NUM_BIT)
  1030. X                                                bad_prog("multiple number options to 's' command");
  1031. X                                        if(cur_cmd->x.cmd_regex.flags&S_GLOBAL_BIT==0)
  1032. X                                                cur_cmd->x.cmd_regex.flags|=S_NUM_BIT;
  1033. X                                        num = 0;
  1034. X                                        while(isdigit(ch)) {
  1035. X                                                num=num*10+ch-'0';
  1036. X                                                ch=inchar();
  1037. X                                        }
  1038. X                                        savchar(ch);
  1039. X                                        cur_cmd->x.cmd_regex.numb=num;
  1040. X                                        break;
  1041. X                                case '\n':
  1042. X                                case ';':
  1043. X                                case EOF:
  1044. X                                        break;
  1045. X                                default:
  1046. X                                        bad_prog("Unknown option to 's'");
  1047. X                                        break;
  1048. X                                }
  1049. X                        } while(ch!=EOF && ch!='\n' && ch!=';');
  1050. X                        if(ch==EOF)
  1051. X                                break;
  1052. X                        break;
  1053. X
  1054. X                case 'y':
  1055. X                        cur_cmd->cmd=ch;
  1056. X                        string=ck_malloc(256);
  1057. X                        for(num=0;num<256;num++)
  1058. X                                string[num]=num;
  1059. X                        b=init_buffer();
  1060. X                        slash=inchar();
  1061. X                        while((ch=inchar())!=EOF && ch!=slash)
  1062. X                                add1_buffer(b,ch);
  1063. X                        cur_cmd->x.translate=string;
  1064. X                        string=get_buffer(b);
  1065. X                        for(num=size_buffer(b);num;--num) {
  1066. X                                ch=inchar();
  1067. X                                if(ch==EOF)
  1068. X                                        bad_prog(BAD_EOF);
  1069. X                                if(ch==slash)
  1070. X                                        bad_prog("strings for y command are different lengths");
  1071. X                                cur_cmd->x.translate[*string++]=ch;
  1072. X                        }
  1073. X                        flush_buffer(b);
  1074. X                        if(inchar()!=slash || inchar()!='\n')
  1075. X                                bad_prog(LINE_JUNK);
  1076. X                        break;
  1077. X
  1078. X                default:
  1079. X                        fprintf(stderr,"sed: Command: %c\n",ch);
  1080. X                        bad_prog("Unknown command");
  1081. X                }
  1082. X        }
  1083. X        return vector;
  1084. X}
  1085. X
  1086. Xbad_prog(why)
  1087. Xchar *why;
  1088. X{
  1089. X        if(prog_line)
  1090. X                fprintf(stderr,"%s: file %s line %d: %s\n",myname,prog_name,prog_line,why);
  1091. X        else
  1092. X                fprintf(stderr,"%s: %s\n",myname,why);
  1093. X        exit(1);
  1094. X}
  1095. X
  1096. Xint
  1097. Xinchar()
  1098. X{
  1099. X        int     ch;
  1100. X        if(prog_file)
  1101. X                ch=getc(prog_file);
  1102. X        else {
  1103. X                if(!prog_cur)
  1104. X                        return EOF;
  1105. X                else if(prog_cur==prog_end) {
  1106. X                        ch=EOF;
  1107. X                        prog_cur=0;
  1108. X                } else
  1109. X                        ch= *prog_cur++;
  1110. X        }
  1111. X        if(ch=='\n' && prog_line)
  1112. X                prog_line++;
  1113. X        return ch;
  1114. X}
  1115. X
  1116. Xvoid
  1117. Xsavchar(ch)
  1118. Xint ch;
  1119. X{
  1120. X        if(ch==EOF)
  1121. X                return;
  1122. X        if(ch=='\n' && prog_line>1)
  1123. X                --prog_line;
  1124. X        if(prog_file)
  1125. X                ungetc(ch,prog_file);
  1126. X        else
  1127. X                *--prog_cur=ch;
  1128. X}
  1129. X
  1130. X
  1131. Xcompile_address(addr)
  1132. Xstruct addr *addr;
  1133. X{
  1134. X        int     ch;
  1135. X        int     num;
  1136. X        char    *b,*init_buffer();
  1137. X
  1138. X        ch=inchar();
  1139. X
  1140. X        if(isdigit(ch)) {
  1141. X                num=ch-'0';
  1142. X                while((ch=inchar())!=EOF && isdigit(ch))
  1143. X                        num=num*10+ch-'0';
  1144. X                while(ch!=EOF && isspace(ch))
  1145. X                        ch=inchar();
  1146. X                savchar(ch);
  1147. X                addr->addr_type=ADDR_NUM;
  1148. X                addr->addr_number = num;
  1149. X                return 1;
  1150. X        } else if(ch=='/') {
  1151. X                addr->addr_type=ADDR_REGEX;
  1152. X                b=init_buffer();
  1153. X                while((ch=inchar())!=EOF && ch!='/') {
  1154. X                        add1_buffer(b,ch);
  1155. X                        if(ch=='\\') {
  1156. X                                ch=inchar();
  1157. X                                if(ch!=EOF)
  1158. X                                        add1_buffer(b,ch);
  1159. X                        }
  1160. X                }
  1161. X                if(size_buffer(b)) {
  1162. X                        last_regex=(struct re_pattern_buffer *)ck_malloc(sizeof(struct re_pattern_buffer));
  1163. X                        last_regex->allocated=size_buffer(b);
  1164. X                        last_regex->buffer=ck_malloc(last_regex->allocated);
  1165. X                        last_regex->fastmap=0;
  1166. X                        last_regex->translate=0;
  1167. X                        re_compile_pattern(get_buffer(b),size_buffer(b),last_regex);
  1168. X                } else if(!last_regex)
  1169. X                        bad_prog(NO_REGEX);
  1170. X
  1171. X                addr->addr_regex=last_regex;
  1172. X                flush_buffer(b);
  1173. X                do ch=inchar();
  1174. X                while(ch!=EOF && isspace(ch));
  1175. X                savchar(ch);
  1176. X                return 1;
  1177. X        } else if(ch=='$') {
  1178. X                addr->addr_type=ADDR_LAST;
  1179. X                do ch=inchar();
  1180. X                while(ch!=EOF && isspace(ch));
  1181. X                savchar(ch);
  1182. X                return 1;
  1183. X        } else
  1184. X                savchar(ch);
  1185. X        return 0;
  1186. X}
  1187. X
  1188. Xstruct sed_label *
  1189. Xsetup_jump(list,cmd,vec)
  1190. Xstruct sed_label *list;
  1191. Xstruct sed_cmd *cmd;
  1192. Xstruct vector *vec;
  1193. X{
  1194. X        struct sed_label *tmp;
  1195. X        VOID *b;
  1196. X        int ch;
  1197. X
  1198. X        b=init_buffer();
  1199. X        while((ch=inchar())!=EOF && ch!='\n')
  1200. X                add1_buffer(b,ch);
  1201. X        add1_buffer(b,'\0');
  1202. X        tmp=(struct sed_label *)ck_malloc(sizeof(struct sed_label));
  1203. X        tmp->v=vec;
  1204. X        tmp->v_index=cmd-vec->v;
  1205. X        tmp->name=strdup(get_buffer(b));
  1206. X        tmp->next=list;
  1207. X        flush_buffer(b);
  1208. X        return tmp;
  1209. X}
  1210. X
  1211. X#define NUM_FPS 32
  1212. Xstruct {
  1213. X        FILE *phile;
  1214. X        char *name;
  1215. X        int readit;
  1216. X} file_ptrs[NUM_FPS];
  1217. X
  1218. XFILE *
  1219. Xcompile_filename(readit)
  1220. X{
  1221. X        char *file_name;
  1222. X        int n;
  1223. X        VOID *b;
  1224. X        int ch;
  1225. X        char **globbed;
  1226. X        extern char **glob_filename();
  1227. X
  1228. X        if(inchar()!=' ')
  1229. X                bad_prog("missing ' ' before filename");
  1230. X        b=init_buffer();
  1231. X        while((ch=inchar())!=EOF && ch!='\n')
  1232. X                add1_buffer(b,ch);
  1233. X        add1_buffer(b,'\0');
  1234. X        file_name=get_buffer(b);
  1235. X        globbed=glob_filename(file_name);
  1236. X        if(globbed==0 || globbed==(char **)-1)
  1237. X                bad_prog("can't parse filename");
  1238. X        if(globbed[0] && globbed[1]!=0)
  1239. X                bad_prog("multiple files");
  1240. X        if(globbed[0])
  1241. X                file_name=globbed[0];
  1242. X        for(n=0;n<NUM_FPS;n++) {
  1243. X                if(!file_ptrs[n].name)
  1244. X                        break;
  1245. X                if(!strcmp(file_ptrs[n].name,file_name)) {
  1246. X                        if(file_ptrs[n].readit!=readit)
  1247. X                                bad_prog("Can't open file for both reading and writing");
  1248. X                        flush_buffer(b);
  1249. X                        return file_ptrs[n].phile;
  1250. X                }
  1251. X        }
  1252. X        if(n<NUM_FPS) {
  1253. X                file_ptrs[n].name=strdup(file_name);
  1254. X                file_ptrs[n].readit=readit;
  1255. X                file_ptrs[n].phile=ck_fopen(file_name,readit ? "r" : "a");
  1256. X                flush_buffer(b);
  1257. X                return file_ptrs[n].phile;
  1258. X        } else {
  1259. X                bad_prog("Hopelessely evil compiled in limit on number of open files.  re-compile sed\n");
  1260. X                return 0;
  1261. X        }
  1262. X}
  1263. X
  1264. Xread_file(name)
  1265. Xchar *name;
  1266. X{
  1267. X        if(*name=='-' && name[1]=='\0')
  1268. X                input_file=stdin;
  1269. X        else {
  1270. X                input_file=fopen(name,"r");
  1271. X                if(input_file==0) {
  1272. X                        bad_input++;
  1273. X                        return;
  1274. X                }
  1275. X        }
  1276. X        while(read_pattern_space()) {
  1277. X                execute_program(the_program);
  1278. X                if(!no_default_output)
  1279. X                        ck_fwrite(line.text,1,line.length,stdout);
  1280. X                if(append.length) {
  1281. X                        ck_fwrite(append.text,1,append.length,stdout);
  1282. X                        append.length=0;
  1283. X                }
  1284. X                if(quit_cmd)
  1285. X                        break;
  1286. X        }
  1287. X        ck_fclose(input_file);
  1288. X}
  1289. X
  1290. Xexecute_program(vec)
  1291. Xstruct vector *vec;
  1292. X{
  1293. X        struct sed_cmd *cur_cmd;
  1294. X        int     n;
  1295. X        int addr_matched;
  1296. X        static int end_cycle;
  1297. X
  1298. X        int start;
  1299. X        int remain;
  1300. X        int offset;
  1301. X
  1302. X        static struct line tmp;
  1303. X        struct line t;
  1304. X        char *rep,*rep_end,*rep_next,*rep_cur;
  1305. X
  1306. X        struct re_registers regs;
  1307. X        int count = 0;
  1308. X        void str_append();
  1309. X
  1310. X
  1311. X        end_cycle = 0;
  1312. X
  1313. X        for(cur_cmd=vec->v,n=vec->v_length;n;cur_cmd++,n--) {
  1314. X
  1315. X        exe_loop:
  1316. X                addr_matched=0;
  1317. X                if(cur_cmd->aflags&A1_MATCHED_BIT) {
  1318. X                        addr_matched=1;
  1319. X                        if(match_address(&(cur_cmd->a2)))
  1320. X                                cur_cmd->aflags&=~A1_MATCHED_BIT;
  1321. X                } else if(match_address(&(cur_cmd->a1))) {
  1322. X                        addr_matched=1;
  1323. X                        if(cur_cmd->a2.addr_type!=ADDR_NULL)
  1324. X                                cur_cmd->aflags|=A1_MATCHED_BIT;
  1325. X                }
  1326. X                if(cur_cmd->aflags&ADDR_BANG_BIT)
  1327. X                        addr_matched= !addr_matched;
  1328. X                if(!addr_matched)
  1329. X                        continue;
  1330. X                switch(cur_cmd->cmd) {
  1331. X                case '{':       /* Execute sub-program */
  1332. X                        execute_program(cur_cmd->x.sub);
  1333. X                        break;
  1334. X
  1335. X                case ':':       /* Executing labels is easy. */
  1336. X                        break;
  1337. X
  1338. X                case '=':
  1339. X                        printf("%d\n",input_line_number);
  1340. X                        break;
  1341. X
  1342. X                case 'a':
  1343. X                        if(append.alloc-append.length<cur_cmd->x.cmd_txt.text_len) {
  1344. X                                append.text=ck_realloc(append.text,append.alloc+cur_cmd->x.cmd_txt.text_len);
  1345. X                                append.alloc+=cur_cmd->x.cmd_txt.text_len;
  1346. X                        }
  1347. X                        bcopy(cur_cmd->x.cmd_txt.text,append.text+append.length,cur_cmd->x.cmd_txt.text_len);
  1348. X                        append.length+=cur_cmd->x.cmd_txt.text_len;
  1349. X                        break;
  1350. X
  1351. X                case 'b':
  1352. X                        if(!cur_cmd->x.jump)
  1353. X                                end_cycle++;
  1354. X                        else {
  1355. X                                struct sed_label *j = cur_cmd->x.jump;
  1356. X
  1357. X                                n= j->v->v_length - j->v_index;
  1358. X                                cur_cmd= j->v->v + j->v_index;
  1359. X                                goto exe_loop;
  1360. X                        }
  1361. X                        break;
  1362. X
  1363. X                case 'c':
  1364. X                        line.length=0;
  1365. X                        if(!(cur_cmd->aflags&A1_MATCHED_BIT))
  1366. X                                ck_fwrite(cur_cmd->x.cmd_txt.text,1,cur_cmd->x.cmd_txt.text_len,stdout);
  1367. X                        end_cycle++;
  1368. X                        break;
  1369. X
  1370. X                case 'd':
  1371. X                        line.length=0;
  1372. X                        end_cycle++;
  1373. X                        break;
  1374. X
  1375. X                case 'D':
  1376. X                        {
  1377. X                                char *tmp;
  1378. X                                int newlength;
  1379. X
  1380. X                                tmp=memchr(line.text,'\n',line.length);
  1381. X                                newlength=line.length-(tmp-line.text+1);
  1382. X                                if(newlength)
  1383. X                                        memmove(line.text,tmp,newlength);
  1384. X                                line.length=newlength;
  1385. X                        }
  1386. X                        end_cycle++;
  1387. X                        break;
  1388. X
  1389. X                case 'g':
  1390. X                        line_copy(&hold,&line);
  1391. X                        break;
  1392. X
  1393. X                case 'G':
  1394. X                        line_append(&hold,&line);
  1395. X                        break;
  1396. X
  1397. X                case 'h':
  1398. X                        line_copy(&line,&hold);
  1399. X                        break;
  1400. X
  1401. X                case 'H':
  1402. X                        line_append(&line,&hold);
  1403. X                        break;
  1404. X
  1405. X                case 'i':
  1406. X                        ck_fwrite(cur_cmd->x.cmd_txt.text,1,cur_cmd->x.cmd_txt.text_len,stdout);
  1407. X                        break;
  1408. X
  1409. X                case 'l':
  1410. X                        {
  1411. X                                char *tmp;
  1412. X                                int n;
  1413. X                                int width = 0;
  1414. X
  1415. X                                n=line.length;
  1416. X                                tmp=line.text;
  1417. X                                /* Use --n so this'll skip the trailing newline */
  1418. X                                while(--n) {
  1419. X                                        if(width>77) {
  1420. X                                                width=0;
  1421. X                                                putchar('\n');
  1422. X                                        }
  1423. X                                        if(isprint(*tmp)) {
  1424. X                                                putchar(*tmp);
  1425. X                                                width++;
  1426. X                                        } else switch(*tmp) {
  1427. X                                        case '\0':
  1428. X                                                printf("\\0");
  1429. X                                                width+=2;
  1430. X                                                break;
  1431. X                                        case '\a':
  1432. X                                                printf("\\a");
  1433. X                                                width+=2;
  1434. X                                                break;
  1435. X                                        case '\b':
  1436. X                                                printf("\\b");
  1437. X                                                width+=2;
  1438. X                                                break;
  1439. X                                        case '\f':
  1440. X                                                printf("\\f");
  1441. X                                                width+=2;
  1442. X                                                break;
  1443. X                                        case '\n':
  1444. X                                                printf("\\n");
  1445. X                                                width+=2;
  1446. X                                                break;
  1447. X                                        case '\r':
  1448. X                                                printf("\\r");
  1449. X                                                width+=2;
  1450. X                                                break;
  1451. X                                        case '\t':
  1452. X                                                printf("\\t");
  1453. X                                                width+=2;
  1454. X                                                break;
  1455. X                                        case '\v':
  1456. X                                                printf("\\v");
  1457. X                                                width+=2;
  1458. X                                                break;
  1459. X                                        default:
  1460. X                                                printf("/%02x",(*tmp)&0xFF);
  1461. X                                                width+=2;
  1462. X                                                break;
  1463. X                                        }
  1464. X                                        tmp++;
  1465. X                                }
  1466. X                                putchar('\n');
  1467. X                        }
  1468. X                        break;
  1469. X
  1470. X                case 'n':
  1471. X                        ck_fwrite(line.text,1,line.length,stdout);
  1472. X                        read_pattern_space();
  1473. X                        break;
  1474. X
  1475. X                case 'N':
  1476. X                        append_pattern_space();
  1477. X                        break;
  1478. X
  1479. X                case 'p':
  1480. X                        ck_fwrite(line.text,1,line.length,stdout);
  1481. X                        break;
  1482. X
  1483. X                case 'P':
  1484. X                        {
  1485. X                                char *tmp;
  1486. X
  1487. X                                tmp=memchr(line.text,'\n',line.length);
  1488. X                                ck_fwrite(line.text,1,line.length-(tmp-line.text),stdout);
  1489. X                        }
  1490. X                        break;
  1491. X
  1492. X                case 'q':
  1493. X                        quit_cmd++;
  1494. X                        end_cycle++;
  1495. X                        break;
  1496. X
  1497. X                case 'r':
  1498. X                        {
  1499. X                                int n;
  1500. X                                char tmp_buf[1024];
  1501. X
  1502. X                                rewind(cur_cmd->x.io_file);
  1503. X                                while((n=fread(tmp_buf,sizeof(char),1024,cur_cmd->x.io_file))>0)
  1504. X                                        ck_fwrite(tmp_buf,sizeof(char),n,stdout);
  1505. X                                if(ferror(cur_cmd->x.io_file))
  1506. X                                        panic("Read error on input file to 'r' command\n");
  1507. X                        }
  1508. X                        break;
  1509. X
  1510. X                case 's':
  1511. X                        if(!tmp.alloc) {
  1512. X                                tmp.alloc=50;
  1513. X                                tmp.text=ck_malloc(50);
  1514. X                        }
  1515. X                        count=0;
  1516. X                        start = 0;
  1517. X                        remain=line.length-1;
  1518. X                        tmp.length=0;
  1519. X                        rep = cur_cmd->x.cmd_regex.replacement;
  1520. X                        rep_end=rep+cur_cmd->x.cmd_regex.replace_length;
  1521. X
  1522. X                        while((offset = re_search(cur_cmd->x.cmd_regex.regx,
  1523. X                                                  line.text,
  1524. X                                                  line.length-1,
  1525. X                                                  start,
  1526. X                                                  remain,
  1527. X                                                  ®s))>=0) {
  1528. X                                count++;
  1529. X                                if(offset-start)
  1530. X                                        str_append(&tmp,line.text+start,offset-start);
  1531. X
  1532. X                                if(cur_cmd->x.cmd_regex.flags&S_NUM_BIT) {
  1533. X                                        if(count!=cur_cmd->x.cmd_regex.numb) {
  1534. X                                                str_append(&tmp,line.text+regs.start[0],regs.end[0]-regs.start[0]);
  1535. X                                                start = (offset == regs.end[0] ? offset + 1 : regs.end[0]);
  1536. X                                                remain = (line.length-1) - start;
  1537. X                                                continue;
  1538. X                                        }
  1539. X                                }
  1540. X
  1541. X                                for(rep_next=rep_cur=rep;rep_next<rep_end;rep_next++) {
  1542. X                                        if(*rep_next=='&') {
  1543. X                                                if(rep_next-rep_cur)
  1544. X                                                        str_append(&tmp,rep_cur,rep_next-rep_cur);
  1545. X                                                str_append(&tmp,line.text+regs.start[0],regs.end[0]-regs.start[0]);
  1546. X                                                rep_cur=rep_next+1;
  1547. X                                        } else if(*rep_next=='\\') {
  1548. X                                                if(rep_next-rep_cur)
  1549. X                                                        str_append(&tmp,rep_cur,rep_next-rep_cur);
  1550. X                                                rep_next++;
  1551. X                                                if(rep_next!=rep_end) {
  1552. X                                                        int n;
  1553. X
  1554. X                                                        if(*rep_next>='0' && *rep_next<='9') {
  1555. X                                                                n= *rep_next -'0';
  1556. X                                                                str_append(&tmp,line.text+regs.start[n],regs.end[n]-regs.start[n]);
  1557. X                                                        } else
  1558. X                                                                str_append(&tmp,&rep_next,1);
  1559. X                                                }
  1560. X                                                rep_cur=rep_next+1;
  1561. X                                        }
  1562. X                                }
  1563. X                                if(rep_next-rep_cur)
  1564. X                                        str_append(&tmp,rep_cur,rep_next-rep_cur);
  1565. X                                start = (offset == regs.end[0] ? offset + 1 : regs.end[0]);
  1566. X                                remain = (line.length-1) - start;
  1567. X                                if(!(cur_cmd->x.cmd_regex.flags&S_GLOBAL_BIT))
  1568. X                                        break;
  1569. X                        }
  1570. X                        if(!count)
  1571. X                                break;
  1572. X                        replaced=1;
  1573. X                        str_append(&tmp,line.text+regs.end[0],line.length-regs.end[0]);
  1574. X                        t.text=line.text;
  1575. X                        t.length=line.length;
  1576. X                        t.alloc=line.alloc;
  1577. X                        line.text=tmp.text;
  1578. X                        line.length=tmp.length;
  1579. X                        line.alloc=tmp.alloc;
  1580. X                        tmp.text=t.text;
  1581. X                        tmp.length=t.length;
  1582. X                        tmp.alloc=t.alloc;
  1583. X                        if(cur_cmd->x.cmd_regex.flags&S_WRITE_BIT)
  1584. X                                ck_fwrite(line.text,1,line.length,cur_cmd->x.cmd_regex.wio_file);
  1585. X                        if(cur_cmd->x.cmd_regex.flags&S_PRINT_BIT)
  1586. X                                ck_fwrite(line.text,1,line.length,stdout);
  1587. X                        break;
  1588. X
  1589. X                case 't':
  1590. X                        if(replaced) {
  1591. X                                replaced = 0;
  1592. X                                if(!cur_cmd->x.jump)
  1593. X                                        end_cycle++;
  1594. X                                else {
  1595. X                                        struct sed_label *j = cur_cmd->x.jump;
  1596. X
  1597. X                                        n= j->v->v_length - j->v_index;
  1598. X                                        cur_cmd= j->v->v + j->v_index;
  1599. X                                        goto exe_loop;
  1600. X                                }
  1601. X                        }
  1602. X                        break;
  1603. X
  1604. X                case 'w':
  1605. X                        ck_fwrite(line.text,1,line.length,cur_cmd->x.io_file);
  1606. X                        break;
  1607. X
  1608. X                case 'x':
  1609. X                        {
  1610. X                                struct line tmp;
  1611. X
  1612. X                                tmp=line;
  1613. X                                line=hold;
  1614. X                                hold=tmp;
  1615. X                        }
  1616. X                        break;
  1617. X
  1618. X                case 'y':
  1619. X                        {
  1620. X                                unsigned char *p,*e;
  1621. X
  1622. X                                for(p=(unsigned char *)(line.text),e=p+line.length;p<e;p++)
  1623. X                                        *p=cur_cmd->x.translate[*p];
  1624. X                        }
  1625. X                        break;
  1626. X
  1627. X                default:
  1628. X                        panic("INTERNAL ERROR: Bad cmd %c\n",cur_cmd->cmd);
  1629. X                }
  1630. X                if(end_cycle)
  1631. X                        break;
  1632. X        }
  1633. X}
  1634. X
  1635. X
  1636. Xmatch_address(addr)
  1637. Xstruct addr *addr;
  1638. X{
  1639. X        switch(addr->addr_type) {
  1640. X        case ADDR_NULL:
  1641. X                return 1;
  1642. X        case ADDR_NUM:
  1643. X                return (input_line_number==addr->addr_number);
  1644. X
  1645. X        case ADDR_REGEX:
  1646. X                return (re_search(addr->addr_regex,
  1647. X                                  line.text,
  1648. X                                  line.length-1,
  1649. X                                  0,
  1650. X                                  line.length-1,
  1651. X                                  0)>=0) ? 1 : 0;
  1652. X
  1653. X        case ADDR_LAST:
  1654. X                return (input_EOF) ? 1 : 0;
  1655. X
  1656. X        default:
  1657. X                panic("INTERNAL ERROR: bad address type\n");
  1658. X                break;
  1659. X        }
  1660. X        return -1;
  1661. X}
  1662. X
  1663. Xint
  1664. Xread_pattern_space()
  1665. X{
  1666. X        int n;
  1667. X        char *p;
  1668. X        int ch;
  1669. X
  1670. X        p=line.text;
  1671. X        n=line.alloc;
  1672. X
  1673. X        input_line_number++;
  1674. X        replaced=0;
  1675. X        for(;;) {
  1676. X                ch=getc(input_file);
  1677. X                if(ch==EOF) {
  1678. X                        if(n==line.alloc)
  1679. X                                return 0;
  1680. X                        *p++='\n';
  1681. X                        --n;
  1682. X                        line.length=line.alloc-n;
  1683. X                        break;
  1684. X                }
  1685. X                *p++=ch;
  1686. X                --n;
  1687. X                if(ch=='\n') {
  1688. X                        line.length=line.alloc-n;
  1689. X                        break;
  1690. X                }
  1691. X                if(n==0) {
  1692. X                        line.text=ck_realloc(line.text,line.alloc*2);
  1693. X                        p=line.text+line.alloc;
  1694. X                        n=line.alloc;
  1695. X                        line.alloc*=2;
  1696. X                }
  1697. X        }
  1698. X        ch=getc(input_file);
  1699. X        if(ch!=EOF)
  1700. X                ungetc(ch,input_file);
  1701. X        else if(last_input_file)
  1702. X                input_EOF++;
  1703. X        return 1;
  1704. X}
  1705. X
  1706. Xvoid
  1707. Xappend_pattern_space()
  1708. X{
  1709. X        char *p;
  1710. X        int n;
  1711. X        int ch;
  1712. X
  1713. X        p=line.text+line.length;
  1714. X        n=line.alloc-line.length;
  1715. X
  1716. X        input_line_number++;
  1717. X        replaced=0;
  1718. X        for(;;) {
  1719. X                ch=getc(input_file);
  1720. X                if(ch==EOF) {
  1721. X                        if(n==line.alloc)
  1722. X                                return;
  1723. X                        *p++='\n';
  1724. X                        --n;
  1725. X                        line.length=line.alloc-n;
  1726. X                        break;
  1727. X                }
  1728. X                *p++=ch;
  1729. X                --n;
  1730. X                if(ch=='\n') {
  1731. X                        line.length=line.alloc-n;
  1732. X                        break;
  1733. X                }
  1734. X                if(n==0) {
  1735. X                        line.text=ck_realloc(line.text,line.alloc*2);
  1736. X                        p=line.text+line.alloc;
  1737. X                        n=line.alloc;
  1738. X                        line.alloc*=2;
  1739. X                }
  1740. X        }
  1741. X        ch=getc(input_file);
  1742. X        if(ch!=EOF)
  1743. X                ungetc(ch,input_file);
  1744. X        else if(last_input_file)
  1745. X                input_EOF++;
  1746. X}
  1747. X
  1748. Xvoid
  1749. Xline_copy(from,to)
  1750. Xstruct line *from,*to;
  1751. X{
  1752. X        if(from->length>to->alloc) {
  1753. X                to->alloc=from->length;
  1754. X                to->text=ck_realloc(to->text,to->alloc);
  1755. X        }
  1756. X        bcopy(from->text,to->text,from->length);
  1757. X        to->length=from->length;
  1758. X}
  1759. X
  1760. Xvoid
  1761. Xline_append(from,to)
  1762. Xstruct line *from,*to;
  1763. X{
  1764. X        if(from->length>(to->alloc-to->length)) {
  1765. X                to->alloc+=from->length;
  1766. X                to->text=ck_realloc(to->text,to->alloc);
  1767. X        }
  1768. X        bcopy(from->text,to->text+to->length,from->length);
  1769. X        to->length+=from->length;
  1770. X}
  1771. X
  1772. Xvoid
  1773. Xstr_append(to,string,length)
  1774. Xstruct line *to;
  1775. Xchar *string;
  1776. Xint length;
  1777. X{
  1778. X        if(length>to->alloc-to->length) {
  1779. X                to->alloc+=length;
  1780. X                to->text=ck_realloc(to->text,to->alloc);
  1781. X        }
  1782. X        bcopy(string,to->text+to->length,length);
  1783. X        to->length+=length;
  1784. X}
  1785. X
  1786. X#ifndef HAS_UTILS
  1787. X
  1788. X#ifdef __STDC__
  1789. X#include "stdarg.h"
  1790. X
  1791. Xpanic(str)
  1792. Xchar *str;
  1793. X{
  1794. X        va_list iggy;
  1795. X
  1796. X        va_start(iggy,str);
  1797. X        fprintf(stderr,"%s: ",myname);
  1798. X#ifdef NO_VFPRINTF
  1799. X        _doprnt(str,&iggy,stderr);
  1800. X#else
  1801. X        vfprintf(stderr,str,iggy);
  1802. X#endif
  1803. X        putc('\n',stderr);
  1804. X        va_end(iggy);
  1805. X        exit(4);
  1806. X}
  1807. X
  1808. X#else
  1809. X#ifdef AZTEC_C
  1810. X
  1811. X/* this kludge inserted because of lack of vfprintf or _doprnt in the
  1812. X * Manx libs, and this was easier than rewriting printf, which I have
  1813. X * no source to! Delete this if and when vfprintf is written on the Amiga.
  1814. X */
  1815. Xpanic(str,arg1,arg2,arg3)
  1816. Xchar *str;
  1817. Xint arg1,arg2,arg3;
  1818. X{
  1819. X  fprintf(stderr,"%s: ",myname);
  1820. X  fprintf(stderr,str,arg1,arg2,arg3);
  1821. X  fprintf(stderr,"\n");
  1822. X  exit(4);
  1823. X}
  1824. X#else
  1825. X#include "varargs.h"
  1826. X
  1827. Xpanic(str,va_alist)
  1828. Xchar *str;
  1829. Xva_dcl
  1830. X{
  1831. X        va_list iggy;
  1832. X
  1833. X        va_start(iggy);
  1834. X        fprintf(stderr,"%s: ",myname);
  1835. X#ifdef NO_VFPRINTF
  1836. X        _doprnt(str,&iggy,stderr);
  1837. X#else
  1838. X        vfprintf(stderr,str,iggy);
  1839. X#endif
  1840. X        putc('\n',stderr);
  1841. X        va_end(iggy);
  1842. X        exit(4);
  1843. X}
  1844. X
  1845. X#endif
  1846. X#endif
  1847. X
  1848. X#define N_FILE 20
  1849. X
  1850. Xstruct id {
  1851. X        FILE *fp;
  1852. X        char *name;
  1853. X};
  1854. X
  1855. Xstatic struct id __id_s[N_FILE];
  1856. X
  1857. Xchar *
  1858. X__fp_name(fp)
  1859. XFILE *fp;
  1860. X{
  1861. X        int n;
  1862. X
  1863. X        for(n=0;n<N_FILE;n++) {
  1864. X                if(__id_s[n].fp==fp)
  1865. X                        return __id_s[n].name;
  1866. X        }
  1867. X        return "{Unknown file pointer}";
  1868. X}
  1869. X
  1870. X/* Panic on failing fopen */
  1871. XFILE *
  1872. Xck_fopen(name,mode)
  1873. Xchar *name;
  1874. Xchar *mode;
  1875. X{
  1876. X        FILE    *ret;
  1877. X        int     n;
  1878. X
  1879. X        ret=fopen(name,mode);
  1880. X        if(ret==(FILE *)0)
  1881. X                panic("Couldn't open file %s\n",name);
  1882. X        for(n=0;n<N_FILE;n++) {
  1883. X                if(ret==__id_s[n].fp) {
  1884. X                        free((VOID *)__id_s[n].name);
  1885. X                        __id_s[n].name=(char *)ck_malloc(strlen(name)+1);
  1886. X                        strcpy(__id_s[n].name,name);
  1887. X                        break;
  1888. X                }
  1889. X        }
  1890. X        if(n==N_FILE) {
  1891. X                for(n=0;n<N_FILE;n++)
  1892. X                        if(__id_s[n].fp==(FILE *)0)
  1893. X                                break;
  1894. X                if(n==N_FILE)
  1895. X                        panic("Internal error: too many files open\n");
  1896. X                __id_s[n].fp=ret;
  1897. X                __id_s[n].name=(char *)ck_malloc(strlen(name)+1);
  1898. X                strcpy(__id_s[n].name,name);
  1899. X        }
  1900. X        return ret;
  1901. X}
  1902. X
  1903. Xvoid
  1904. Xck_fwrite(ptr,size,nmemb,stream)
  1905. Xchar *ptr;
  1906. Xint size,nmemb;
  1907. XFILE *stream;
  1908. X{
  1909. X        if(fwrite(ptr,size,nmemb,stream)!=nmemb)
  1910. X                panic("couldn't write %d items to %s",nmemb,__fp_name(stream));
  1911. X}
  1912. X
  1913. Xvoid
  1914. Xck_fclose(stream)
  1915. XFILE *stream;
  1916. X{
  1917. X        if(fclose(stream)==EOF)
  1918. X                panic("Couldn't close %s\n",__fp_name(stream));
  1919. X}
  1920. X
  1921. XVOID *
  1922. Xck_malloc(size)
  1923. Xint size;
  1924. X{
  1925. X        VOID *ret;
  1926. X        VOID *malloc();
  1927. X
  1928. X        ret=malloc(size);
  1929. X        if(ret==(VOID *)0)
  1930. X                panic("Couldn't allocate memory\n");
  1931. X        return ret;
  1932. X}
  1933. X
  1934. XVOID *
  1935. Xck_realloc(ptr,size)
  1936. XVOID *ptr;
  1937. Xint size;
  1938. X{
  1939. X        VOID *ret;
  1940. X        VOID *realloc();
  1941. X
  1942. X        ret=realloc(ptr,size);
  1943. X        if(ret==(VOID *)0)
  1944. X                panic("Couldn't re-allocate memory\n");
  1945. X        return ret;
  1946. X}
  1947. X
  1948. Xchar *
  1949. Xstrdup(str)
  1950. Xchar *str;
  1951. X{
  1952. X        char *ret;
  1953. X
  1954. X        ret=(char *)ck_malloc(strlen(str)+2);
  1955. X        strcpy(ret,str);
  1956. X        return ret;
  1957. X}
  1958. X
  1959. X
  1960. X#ifndef AZTEC_C
  1961. X/*
  1962. X * memmove - copy bytes, being careful about overlap.
  1963. X */
  1964. X
  1965. XVOID *
  1966. Xmemmove(dst, src, size)
  1967. XVOID *dst;
  1968. XVOID *src;
  1969. Xint size;
  1970. X{
  1971. X        register char *d;
  1972. X        register char *s;
  1973. X        register int n;
  1974. X
  1975. X        if (size <= 0)
  1976. X                return(dst);
  1977. X
  1978. X        s = (char *)src;
  1979. X        d = (char *)dst;
  1980. X        if (s <= d && s + (size-1) >= d) {
  1981. X                /* Overlap, must copy right-to-left. */
  1982. X                s += size-1;
  1983. X                d += size-1;
  1984. X                for (n = size; n > 0; n--)
  1985. X                        *d-- = *s--;
  1986. X        } else
  1987. X                for (n = size; n > 0; n--)
  1988. X                        *d++ = *s++;
  1989. X
  1990. X        return(dst);
  1991. X}
  1992. X#else
  1993. X
  1994. XVOID *
  1995. Xmemmove(dst,src,size)
  1996. XVOID *dst;
  1997. XVOID *src;
  1998. Xint size;
  1999. X{
  2000. X  return ( (VOID *) movmem(src,dst,size) );
  2001. X}
  2002. X
  2003. XVOID *memchr(mem,val,len)
  2004. Xchar *mem;
  2005. Xint val,len;
  2006. X{
  2007. X  register int index = 0;
  2008. X
  2009. X  while ( index < len ) {
  2010. X    if ( mem[index] == (char) val ) {
  2011. X      return(&mem[index]);
  2012. X    }
  2013. X    ++index;
  2014. X  }
  2015. X
  2016. X  return(NULL);
  2017. X}
  2018. X
  2019. X#endif
  2020. X
  2021. X/* Implement a variable sized buffer of 'stuff'.  We don't know what it is,
  2022. X   nor do we care, as long as it doesn't mind being aligned on a char boundry.
  2023. X   'b' could be made non-global, with a little work, so we could have more
  2024. X   than one buffer, but we don't need more than one, so why bother? */
  2025. X
  2026. X
  2027. Xstruct buffer {
  2028. X        int     allocated;
  2029. X        int     length;
  2030. X        char    *b;
  2031. X};
  2032. X
  2033. X#define MIN_ALLOCATE 50
  2034. X
  2035. XVOID *
  2036. Xinit_buffer()
  2037. X{
  2038. X        struct buffer *b;
  2039. X
  2040. X        b=(struct buffer *)ck_malloc(sizeof(struct buffer));
  2041. X        b->allocated=MIN_ALLOCATE;
  2042. X        b->b=(char *)ck_malloc(MIN_ALLOCATE);
  2043. X        b->length=0;
  2044. X        return (VOID *)b;
  2045. X}
  2046. X
  2047. Xvoid
  2048. Xflush_buffer(bb)
  2049. XVOID *bb;
  2050. X{
  2051. X        struct buffer *b;
  2052. X
  2053. X        b=(struct buffer *)bb;
  2054. X        free(b->b);
  2055. X        b->b=0;
  2056. X        b->allocated=0;
  2057. X        b->length=0;
  2058. X        free(b);
  2059. X}
  2060. X
  2061. Xint
  2062. Xsize_buffer(b)
  2063. XVOID *b;
  2064. X{
  2065. X        struct buffer *bb;
  2066. X
  2067. X        bb=(struct buffer *)b;
  2068. X        return bb->length;
  2069. X}
  2070. X
  2071. Xvoid
  2072. Xadd_buffer(bb,p,n)
  2073. XVOID *bb;
  2074. Xchar *p;
  2075. Xint n;
  2076. X{
  2077. X        struct buffer *b;
  2078. X
  2079. X        b=(struct buffer *)bb;
  2080. X        if(b->length+n>b->allocated) {
  2081. X                b->allocated*=2;
  2082. X                b->b=(char *)ck_realloc(b->b,b->allocated);
  2083. X        }
  2084. X        bcopy(p,b->b+b->length,n);
  2085. X        b->length+=n;
  2086. X}
  2087. X
  2088. Xvoid
  2089. Xadd1_buffer(bb,ch)
  2090. XVOID *bb;
  2091. Xint ch;
  2092. X{
  2093. X        struct buffer *b;
  2094. X
  2095. X        b=(struct buffer *)bb;
  2096. X        if(b->length+1>b->allocated) {
  2097. X                b->allocated*=2;
  2098. X                b->b=(char *)ck_realloc(b->b,b->allocated);
  2099. X        }
  2100. X        b->b[b->length]=ch;
  2101. X        b->length++;
  2102. X}
  2103. X
  2104. Xchar *
  2105. Xget_buffer(bb)
  2106. XVOID *bb;
  2107. X{
  2108. X        struct buffer *b;
  2109. X
  2110. X        b=(struct buffer *)bb;
  2111. X        return b->b;
  2112. X}
  2113. X
  2114. X#endif
  2115. SHAR_EOF
  2116. echo "extracting sed.man"
  2117. sed 's/^X//' << \SHAR_EOF > sed.man
  2118. X
  2119. X
  2120. X
  2121. XSED(1)                    User Commands                     SED(1)
  2122. X
  2123. X
  2124. X
  2125. XNAME
  2126. X     sed - stream editor
  2127. X
  2128. XSYNOPSIS
  2129. X     sed [ -n ] [ -e script ] [ -f scriptfile ] [ files ]
  2130. X
  2131. XDESCRIPTION
  2132. X     Sed copies the named files or the standard input to its
  2133. X     standard output, while performing certain operations speci-
  2134. X     fied in the command line script or in the file scriptfile.
  2135. X     If no filenames are specified, the default input is the
  2136. X     standard input.
  2137. X
  2138. X     Sed cyclically reads in input lines and places them in the
  2139. X     pattern space.  The pattern space is selected by some or all
  2140. X     of the commands in the script, and acted upon by these com-
  2141. X     mands. The pattern space is then written to the output, and
  2142. X     the next input is read.
  2143. X
  2144. X     The script (on the command line or in the script file) is
  2145. X     composed of one or more lines that have the following form:
  2146. X
  2147. X     [ range ] function [ arguments ]
  2148. X
  2149. X     The range refers to either a line address range or a regular
  2150. X     expression in the style of ed(1). The range selects which
  2151. X     input lines the function should act upon. If the range is
  2152. X     omitted, all input lines are selected.
  2153. X
  2154. X     The line address is calculated sequentially from the first
  2155. X     file to last, in order. A line address range may be either a
  2156. X     single line number or two line numbers separated by a comma.
  2157. X     A single number selects that line number to act upon, and
  2158. X     two line numbers separated by a comma inclusively select all
  2159. X     lines between those two numbers.
  2160. X
  2161. X     Regular expressions in sed differ from ed(1) regular expres-
  2162. X     sions in that the escape sequence `\n' matches a newline
  2163. X     embedded in the pattern space.  A $ character may also be
  2164. X     used to select the last line of input.
  2165. X
  2166. X     The following list of sed functions are preceded by a number
  2167. X     indicating the maximum amount of line numbers valid in the
  2168. X     range of the function. A (1) would indicate that the func-
  2169. X     tion can only take effect after a certain line number and
  2170. X     not a range of line numbers, while a (2) would indicate that
  2171. X     either one line number or two are valid for the function.
  2172. X
  2173. X     When a function takes a text argument, a newline in the text
  2174. X     may be escaped by placing a `\' character before it, allow-
  2175. X     ing multiline texts.
  2176. X
  2177. X
  2178. X
  2179. X
  2180. XGNU Project                1989 May 26                          1
  2181. X
  2182. X
  2183. X
  2184. X
  2185. X
  2186. X
  2187. XSED(1)                    User Commands                     SED(1)
  2188. X
  2189. X
  2190. X
  2191. X     Empty commands are ignored.
  2192. X
  2193. X     A wfile or rfile argument to a function must be at the end
  2194. X     of a command line, and there must be exactly one space
  2195. X     between the command and the file name argument. There can be
  2196. X     at most 10 wfile and rfile arguments.  All wfile or rfile
  2197. X     arguments are created before any input lines are read.
  2198. X
  2199. X     (1)a\
  2200. X     text
  2201. X          Append the text to the output after the current pattern
  2202. X          space.
  2203. X
  2204. X     (2)b label
  2205. X          Branch to the label defined with the `:' command. An
  2206. X          empty label implies a branch to the end of the script.
  2207. X
  2208. X     (2)c\
  2209. X     text
  2210. X          Change text.  The pattern space is unconditionally
  2211. X          deleted and the text is written to the output following
  2212. X          the range.
  2213. X
  2214. X     (2)d Delete the pattern space.
  2215. X
  2216. X     (2)D Delete the initial segment of the pattern space up to
  2217. X          and including the first newline.  (the pattern space
  2218. X          may contain more than one line of text -- see the `N'
  2219. X          command)
  2220. X
  2221. X     (2)g Overwrite the pattern space with the contents of the
  2222. X          hold space.
  2223. X
  2224. X     (2)G Append the contents of the hold space to the pattern
  2225. X          space.
  2226. X
  2227. X     (2)h Hold the pattern space. The pattern space is copied
  2228. X          into the hold space.
  2229. X
  2230. X     (2)H Append the pattern space to the hold space.
  2231. X
  2232. X     (1)i\
  2233. X     text
  2234. X          Insert.  Write text to the output.
  2235. X
  2236. X     (2)n Flush the pattern space to the output and read the next
  2237. X          input line into the pattern space.
  2238. X
  2239. X     (2)N Append the next line of input to the pattern space,
  2240. X          inserting a newline character between them.
  2241. X
  2242. X
  2243. X
  2244. X
  2245. X
  2246. XGNU Project                1989 May 26                          2
  2247. X
  2248. X
  2249. X
  2250. X
  2251. X
  2252. X
  2253. XSED(1)                    User Commands                     SED(1)
  2254. X
  2255. X
  2256. X
  2257. X     (2)p Print.  Write a copy of the pattern space to the out-
  2258. X          put.
  2259. X
  2260. X     (2)P Write a copy of the pattern space up to and including
  2261. X          the first newline to the output.
  2262. X
  2263. X     (1)q Quit and do not start a new cycle.
  2264. X
  2265. X     (2)r rfile
  2266. X          Read the contents of rfile and write them to the out-
  2267. X          put.
  2268. X
  2269. X     (2)s/regular expression/replacement/flags
  2270. X          Search for the regular expression in the pattern space
  2271. X          and replace it with the replacement string.  Any char-
  2272. X          acter may be used as a delimiter instead of the `/'.
  2273. X          The flags argument may be any number of the following:
  2274. X
  2275. X          g    Globally substitute the replacement for the regu-
  2276. X               lar expression. Normally, only the first match is
  2277. X               found, but g forces matching of all occurances.
  2278. X
  2279. X          p    Print the pattern space if a replacement was made.
  2280. X
  2281. X          w wfile
  2282. X               Write the pattern space to the end of wfile if a
  2283. X               replacement was made. This must be the last flag
  2284. X               argument if it is used.
  2285. X
  2286. X     (2)t label
  2287. X          Test.  If a substitution was made since the last time
  2288. X          an input line was read into the pattern space, or since
  2289. X          the last `t' command, command branches to the label. An
  2290. X          empty label means to branch to the end of the script.
  2291. X
  2292. X     (2)w wfile
  2293. X          Write the pattern space to the file wfile.
  2294. X
  2295. X     (2)x Exchange the contents of the pattern and hold spaces.
  2296. X
  2297. X     (2)y/string1/string2/
  2298. X          Yank all characters in string1 and replace them with
  2299. X          the corresponding characters in string2, which should
  2300. X          be of equal length as string1.
  2301. X
  2302. X     (2)! function
  2303. X          Apply the function to those lines not selected by the
  2304. X          command.
  2305. X
  2306. X     (0): label
  2307. X          Declare a label for `b' and `t' commands to branch to.
  2308. X
  2309. X
  2310. X
  2311. X
  2312. XGNU Project                1989 May 26                          3
  2313. X
  2314. X
  2315. X
  2316. X
  2317. X
  2318. X
  2319. XSED(1)                    User Commands                     SED(1)
  2320. X
  2321. X
  2322. X
  2323. X     (1)= Write the current line number to the output.
  2324. X
  2325. X     (2){ Perform multiple commands on the range. The `{' charac-
  2326. X          ter is followed by one or more commands to perform on
  2327. X          the pattern space. A '}' character terminates the list
  2328. X          of commands.
  2329. X
  2330. XOPTIONS
  2331. X     -n      suppress the default output
  2332. X
  2333. X     -e      indicates that the next argument is a script. Useful
  2334. X             for scripts starting with a - character.
  2335. X
  2336. X     -f      indicates that the following argument is a file con-
  2337. X             taining a script of commands to Sed.
  2338. X
  2339. XSEE ALSO
  2340. X     ed(1), grep(1), awk(1), lex(1)
  2341. X
  2342. XAVAILABILITY
  2343. X     GNU sed is free; anyone may redistribute copies of sed to
  2344. X     anyone under the terms stated in the GNU General Public
  2345. X     License, a copy of which may be found in each copy of GNU
  2346. X     Emacs.  See also the comment at the beginning of the source
  2347. X     code file sed.c.
  2348. X
  2349. X     Copies of GNU sed may sometimes be received packaged with
  2350. X     distributions of Unix systems, but it is never included in
  2351. X     the scope of any license covering those systems.  Such
  2352. X     inclusion violates the terms on which distribution is per-
  2353. X     mitted.  In fact, the primary purpose of the General Public
  2354. X     License is to prohibit anyone from attaching any other res-
  2355. X     trictions to redistribution of any of the Free Software
  2356. X     Foundation programs.
  2357. X
  2358. X
  2359. X
  2360. X
  2361. X
  2362. X
  2363. X
  2364. X
  2365. X
  2366. X
  2367. X
  2368. X
  2369. X
  2370. X
  2371. X
  2372. X
  2373. X
  2374. X
  2375. X
  2376. X
  2377. X
  2378. XGNU Project                1989 May 26                          4
  2379. X
  2380. X
  2381. X
  2382. SHAR_EOF
  2383. echo "End of archive 3 (of 3)"
  2384. # if you want to concatenate archives, remove anything after this line
  2385. exit
  2386.